﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using TrackSystem.Contracts;
using TrackSystem.Entities.Dtos.Logic;
using TrackSystem.Entities.Models;
using TrackSystem.Entities.RequestFeatures;
using TrackSystem.EntityFramework.Repositories.Extensions;
using TrackSystem.IO.Formula;

namespace TrackSystem.EntityFramework.Repositories
{
    public class LogicRepository : Repositories<LogicTable, int>, ILogicRepository
    {
        private readonly IMapper _mapper;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbContent">数据库接口</param>
        /// <param name="Mapper">类型映射接口</param>
        public LogicRepository(TkDBContent dbContent, IMapper mapper) : base(dbContent)
        {
            _mapper = mapper;
        }

        /// <summary>
        /// 获取所有的逻辑表达式
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<LogicTable>> GetLogicWithEquipAsync()
        {
            return await _dbContext.Logic.Select(x => x)
                .OrderBy(a => a.Id)
                .Include(a => a.Equip)
                .ToListAsync();
        }


        public PagedList<LogicTable> GetPagedLogics(RequestParameter parameter)
        {
            return Table.OrderByQuery(parameter.QueryString)
                .OrderBy(a => a.Id)
                .Include(a => a.Equip)
                .ToPagedList(parameter.PageNumber, parameter.PageSize);
        }

        public async Task<LogicDto> GetSingle(int id)
        {
            var entity = await _dbContext.Logic.SingleAsync(x => x.Id == id);
            return _mapper.Map<LogicDto>(entity);

        }



        /// <summary>
        /// 删除逻辑表达式
        /// </summary>
        /// <param name="id">表达式ID号</param>
        /// <returns></returns>
        public async Task<ApiResult<LogicDto>> DeleteLogicAsync(int id)
        {
            try
            {
                var entity = _dbContext.Logic.FirstOrDefault(x => x.Id == id);
                if (entity == null)
                {
                    return ApiResult<LogicDto>.Fail($"没有发现ID号为{id}的逻辑表达式");
                }
                
                await DeleteAsync(entity);
    
                var dto = _mapper.Map<LogicDto>(entity);
                return ApiResult<LogicDto>.Ok(dto);
            }
            catch (Exception e)
            {
                return ApiResult<LogicDto>.Fail($"删除逻辑表达式错误, {e.Message}");
            }
        }


        /// <summary>
        /// 添加逻辑表达式
        /// </summary>
        /// <param name="table">表达式内容</param>
        /// <returns></returns>
        public async Task<ApiResult<LogicDto>> InsertLogicAsync(LogicTable table)
        {
            try
            {
                var counter = await CountAsync(a => a.Name == table.Name);
                if (counter > 0)
                {
                    return ApiResult<LogicDto>.Fail($"存在同名的逻辑表达式(Name: {table.Name})");
                }
                
                counter = await _dbContext.Equip.CountAsync(a => a.Id == table.equipId);
                if (counter == 0)
                {
                    return ApiResult<LogicDto>.Fail("逻辑表达式所属设备不存在");
                }
                
                var varNameTypes = await _dbContext.Vars
                    .Select(a => new { a.Name, a.DataType })
                    .ToDictionaryAsync(a => a.Name, b => b.DataType);
                
                var resultContent = PageAnalysis.TestPageFormula(table.ClacateFormula, varNameTypes, out var oRegs);
                if (!resultContent.Success)
                {
                    return ApiResult<LogicDto>.Fail(resultContent.Message ??= "表达式内容格式错误");
                }

                table.ResultReg ??= "";
                foreach (var reg in oRegs.Keys)
                {
                    table.ResultReg += $"{reg}, ";
                }

                var resultCodition = ClacuationFormula.TestFormula(table.ConditionFormula ??= "", varNameTypes);
                if (!resultCodition.Success)
                {
                    return ApiResult<LogicDto>.Fail(resultCodition.Message ??= "表达式条件格式错误");
                }
                
                var entity = await InsertAsync(table);
                if (entity == null)
                {
                    return ApiResult<LogicDto>.Fail("添加逻辑表达式失败");
                }                
                return ApiResult<LogicDto>.Ok(_mapper.Map<LogicDto>(entity));
            }
            catch (Exception e)
            {
                return ApiResult<LogicDto>.Fail($"添加逻辑表达式错误, {e.Message}");
            }
        }

        /// <summary>
        /// 更新逻辑表达式
        /// </summary>
        /// <param name="table">表达式</param>
        /// <returns></returns>
        public async Task<ApiResult<LogicDto>> UpdateLogicAsync(LogicTable table)
        {
            try
            {
                var counter = await CountAsync(a => a.Name == table.Name && a.Id != table.Id);
                if (counter > 0)
                {
                    return ApiResult<LogicDto>.Fail($"存在同名的逻辑表达式(Name: {table.Name})");
                }
                
                counter = await _dbContext.Equip.CountAsync(a => a.Id == table.equipId);
                if (counter == 0)
                {
                    return ApiResult<LogicDto>.Fail("逻辑表达式所属设备不存在");
                }
                
                var varNameTypes = await _dbContext.Vars
                    .Select(a => new { a.Name, a.DataType })
                    .ToDictionaryAsync(a => a.Name, b => b.DataType);
                
                var resultContent = PageAnalysis.TestPageFormula(table.ClacateFormula ??= "", varNameTypes, out var oRegs);
                if (!resultContent.Success)
                {
                    return ApiResult<LogicDto>.Fail(resultContent.Message ??= "表达式内容格式错误");
                }
                table.ResultReg ??= "";
                foreach (var reg in oRegs.Keys)
                {
                    table.ResultReg += $"{reg}, ";
                }

                var resultCodition = ClacuationFormula.TestFormula(table.ConditionFormula ??= "", varNameTypes);
                if (!resultCodition.Success)
                {
                    return ApiResult<LogicDto>.Fail(resultCodition.Message ??= "表达式条件格式错误");
                }
                
                table.Equip = _dbContext.Equip.FirstOrDefault(a => a.Id == table.equipId);
                var entity = await UpdateAsync(table);
                var dto = _mapper.Map<LogicDto>(entity);
                return ApiResult<LogicDto>.Ok(dto);
            }
            catch (Exception e)
            {
                return ApiResult<LogicDto>.Fail($"更新逻辑表达式错误, {e.Message}");
            }        
        }
    }
}
